require.def('pages/relevant',
['config', 'pages', 'pages/control', 'db', 'db/prediction', 'se/api', 'filters', 'stats/fuzz'],
function(Config, Pages, Control, Db, Prediction, Api, Filters){

    return {
        /**
         * @param seListFunc the name of the function on the se api object that gets the question list
         */
        inject: function(seListFunc){ 
            var controller = new Control.PageController('odds'); 
            controller.disablePager();//we don't want the user to be able to do anything yet
            controller.getContentMgr().setLoadingInformation('Training...');
            controller.setContentMgr(new Control.QuestionList());


            var inferenceEnabled = localStorage.getItem('inference.enabled');
            inferenceEnabled = ( inferenceEnabled == null || inferenceEnabled == 'true' )
           
            //check that the tags exist 
            var tags = localStorage.getItem('inference.tags');
            if ( tags === null || $.trim(tags).length == 0 ){
                var msg = 'No tags defined, you must define a set of tags you are intrested on'
                        + ' the <a href="'
                        + 'http://stackoverflow.com/users/'+SiteInformation.UserId+'/#tab=stacked%20odds'
                        + '">options menu</a>';
                controller.getContentMgr().showError(msg);
                return;
            }
            tags = tags.replace(/s+/g, '')
                       .split(' ');

            var seapi = new Api.Api(SiteInformation.ApiUrl, Config.ApiKey);
            var preDb = new Prediction.PredictionDb(Db.getDb(Config.SiteDb));

            var mgr = controller.getContentMgr(); 
            preDb.getAnswers(null, {
                notFound:function(tx){
                    running = false;
                    mgr.showError('No predictions data. Use the stacked odds options menu (accessed via your profile) to create it');
                },
                success:function(tx, answers){
                    var mean = answers.reduce(function(x, e){ return x + e.UpVotes - e.DownVotes; }, 0) / answers.length;
                    var fuzz = new Fuzzy(tags, mean/2);

                    answers.forEach(function(answer){
                        fuzz.train(answer);
                    });
                    controller.enablePager();

                    controller.setPageLoader(function(offset, size, callback){
                        controller.getContentMgr().setContent('');

                        var count = 0; //number of items looked at
                        var found = 0; //number of items that matched the requirements
                        var running = true; //set to false to stop the execution of the loop

                        //stop if we have got enoguh items to fill the page or are
                        //over the max item limit
                        var stopFunc = function(){ 
                            return  !running
                                    || found >= controller.getPageSize()
                                    || count >= Config.ItemCheckLimit;
                        }

                        var preFilters = Filters.getPreChain();
                        var postFilters = Filters.getPostChain();
                        seapi[seListFunc]({body:true}, Api.from(offset).until(stopFunc)).each({
                                step:function(question){
                                    count++;

                                    preFilters.test(seapi, question, {
                                        valid:function(){
                                            if ( inferenceEnabled &&
                                                 fuzz.guess({QuestionTags:question.tags}) < 0.35 ){
                                                return;
                                            }
                                            postFilters.test(seapi, question, {
                                                valid:function(){
                                                    //var g = fuzz.guess({QuestionTags:question.tags})
                                                    //question.score = g;
                                                    mgr.addQuestion(question); 
                                                    found++;
                                                },
                                                error:function(e){
                                                    running = false;
                                                    mgr.showError(e);
                                                }
                                            });
                                        },
                                        error:function(e){
                                            running = false;
                                            mgr.showError(e);
                                        }
                                    });

                                },
                                done:function(){
                                    //send the new offset back so that it can be used in other requests
                                    callback(offset + count);
                                },
                                error:function(e){
                                    running = false;
                                    mgr.showError(e);
                                }

                            }
                        );
                    });

                    //this loads the first set of data
                    controller.load();

                },
                error:function(err){
                    controller.getContentMgr().showError(err);
                }
            });

        }
    }

});

